function Calendar(id){
	var _parentId = id;
	var _curYear;
	var _curMonth;
	var _curDate;
	var _table;
	var _selectedColId = 0;
	var TABLE_BODY_BK_COLOR = "white";
	var TABLE_LABEL_BK_COLOR = "#E78F28";
	var SEL_COL_BK_COLOR = "#B8D4E8";
	var CONTENT_FONT_COLOR = "black";
	var OTHER_FONT_COLOR = "#7F7F7F";
	var HOVER_BK_COLOR = "#DEE6EE";
	var COL_ID_ARRAY_LENGTH = 3;
	var TABLE_COL_MAX_COUNT = 7;
	var WEEKDAYS = new Array(7);
	
	var _tasksView;

	// constructor
	{
		var cdt = new Date();
		_curYear = cdt.getFullYear();
		_curMonth = cdt.getMonth() + 1;
		_curDate = cdt.getDate();
		
	    WEEKDAYS[0] = "周日";
        WEEKDAYS[1] = "周一";
        WEEKDAYS[2] = "周二";
        WEEKDAYS[3] = "周三";
        WEEKDAYS[4] = "周四";
        WEEKDAYS[5] = "周五";
        WEEKDAYS[6] = "周六"; 
		
		createTable();
		buildData(_table, _curYear, _curMonth, _curDate);
	}
	
	this.setTasksView = function(view){
		_tasksView = view;
		_tasksView.setCalendar(this);
	}
	
	// create a table
	function createTable(){
		var parent = document.getElementById(_parentId);
		if(parent == null){
			alert("the parent element can't be got by the id " + _parentId);
			return;
		}		
		_table = document.createElement("table");		
		parent.appendChild(_table);
		_table.id = _parentId + "_cal_table";
		_table.cellSpacing = "0";
		_table.className = "calendar";
		
		_table.appendChild(createHead());
		_table.appendChild(createTitle());		
		_table.appendChild(createTBody(_table));
		_table.appendChild(createDateShow());
	}
		
	function createHead(){
		// create the first row for the table
		var head = document.createElement("tr");
		head.className = "cal-head";
		var col = document.createElement("td");
		head.appendChild(col);
		col.colSpan = TABLE_COL_MAX_COUNT;
		col.className = "head-col";	
		col.appendChild(createButton("calendar_pre", "《", lastMonth));		
		var date_show = document.createElement("span");
		col.appendChild(date_show);
		date_show.id = "calendar_date_show";		
		date_show.className = "date-show";
		col.appendChild(createButton("calendar_nxt", "》", nextMonth));
		col.appendChild(createButton("calendar_today", "今天", goToday));
		
		return head;
	}
		
	function createButton(id, value, f_onclick){
		var btn = document.createElement("input");
		btn.id = id;
		btn.type = "button";
		btn.value = value;
		btn.onclick = f_onclick;
		//btn.style.background = "#B8D4E8";
		//btn.style.color = "white";
		return btn;
	}
	
	function goToday(){
		setCurrentDate(new Date());		
		updateCalendarWithDate(_curYear, _curMonth, _curDate);
		updateTasksView(_curYear, _curMonth, _curDate);
		this.blur();
	}
	
	function setCurrentDate(date){
		if(date != null){
			_curYear = date.getFullYear();
			_curMonth = date.getMonth() + 1;
			_curDate = date.getDate();
		}		
	}
	
	function createTitle(values){
		var row = document.createElement("tr");
		for(var i = 0; i < WEEKDAYS.length; i+=1){
			col = document.createElement("td");
			row.appendChild(col);
			col.innerHTML = WEEKDAYS[i].substring(1);
			col.className = "cal-title";
		}
		
		return row;
	}
			
	function createTBody(table){
		var tbody = document.createElement("tbody");
		tbody.id = table.id + "_tbody";		
		tbody.className = "cal-body";
		var row = null;
		for(i = 0; i < 6; i+=1){
			var row = document.createElement("tr");
			tbody.appendChild(row);
			for(j = 0; j < 7; j+=1){
				var col = document.createElement("td");
				row.appendChild(col);
				col.className = "data-col";
				
				col.onmouseover = function(){
					this.style.background = HOVER_BK_COLOR;
				}				
				col.onmouseout = function(){
					this.style.background = (this.id == _selectedColId) ? SEL_COL_BK_COLOR : TABLE_BODY_BK_COLOR;
				}
				col.onclick = function(){
					decorateSelectedCol(this);		
					updateTasksView(_curYear, _curMonth, _curDate);
				}	
			}
		}
		return tbody;
	}
	
	function decorateSelectedCol(col){
		if(col != null){
			var dts = col.id.split("_");
			if(dts.length != COL_ID_ARRAY_LENGTH){
				alert("wrong date array!");
			}
			var y = parseInt(dts[0]);
			var m = parseInt(dts[1]);
			var d = parseInt(dts[2]);
			if(y != _curYear || m != _curMonth){
				buildData(_table, y, m, d);	
			}
			else {	
				document.getElementById(_selectedColId).style.background = TABLE_BODY_BK_COLOR;					
				_selectedColId = col.id;
				col.style.background = SEL_COL_BK_COLOR;
			}					
			_curYear = y;
			_curMonth = m;
			_curDate = d;	
		}
	}
	
	function createDateShow(){
		var row = document.createElement("tr");
		var col = document.createElement("td");
		row.appendChild(col);
		col.colSpan = TABLE_COL_MAX_COUNT;
		col.className = "date-show";
		var cdt = new Date();		
		col.innerHTML = "今天是 " + cdt.getFullYear() + "-" + (cdt.getMonth() + 1) 
								+ "-" + cdt.getDate() + " " + WEEKDAYS[cdt.getDay()];
		return row;
	}
	
	function updateTasksView(year, month, date){
		if(_tasksView != null){
			_tasksView.getNewCycle(new Date(year, month - 1, date));
		}
		else {
			alert("NULL instance of task view");
		}
	}
	
	function buildData(table, year, month, date){
		setHeadText(year, month);
		
		var fweek = (new Date(year, month - 1, 1)).getDay();
		var md = (new Date(year, month, 0)).getDate();
		if(date > md){
			date = md;
			_curDate = md;
		}
		var max = md + fweek;
		// last month
		var lstMonth = (month == 1) ? 12 : month - 1;
		var lstYear = (month == 1) ? year - 1 : year;
		var lstMax = (new Date(lstYear, lstMonth, 0).getDate())
		// next month
		var nxtMonth = (month == 12) ? 12 : month + 1;
		var nxtYear = (month == 12) ? year + 1 : year;
		var tbody = document.getElementById(table.id + "_tbody");
		if(tbody == null){
			alert("tbody is null");
			return;
		}
		var colIndex = 0;
		for(i = 0; i < tbody.childNodes.length; i+=1){
			var row = tbody.childNodes[i];
			for(j = 0; j < row.childNodes.length; j+=1){				
				var col = row.childNodes[j];
				col.style.background = TABLE_BODY_BK_COLOR;
				var num = 0;
				if(colIndex < fweek || colIndex >= max){					
					if(colIndex < fweek){
						num = lstMax - fweek + colIndex + 1;	
						col.id = genColId(lstYear, lstMonth, num);							
					}
					else{					
						num = colIndex - max + 1;
						col.id = genColId(nxtYear, nxtMonth, num);
					}	
					
					col.style.color = OTHER_FONT_COLOR;				
				}			
				else {				
					num = colIndex - fweek + 1;					
					col.id = genColId(year, month, num);	
					if(num == date){
						_selectedColId = col.id;
						col.style.background = SEL_COL_BK_COLOR;
					}
					col.style.color = CONTENT_FONT_COLOR;
				}				
				col.innerHTML = num;
				colIndex += 1;
			}
		}		
	}
	
	function genColId(year, month, date){
		return year + "_" + month + "_" + date;
	}

	function lastMonth(){
		_curYear = (_curMonth == 1) ? _curYear - 1 : _curYear;
		_curMonth = (_curMonth == 1) ? 12 : _curMonth - 1;
		updateCalendarWithDate(_curYear, _curMonth, _curDate);
		//updateTasksView(_curYear, _curMonth, _curDate);
		this.blur();
	}
	
	function nextMonth(){
		_curYear = (_curMonth == 12) ? (_curYear + 1) : _curYear;
		_curMonth = (_curMonth == 12) ? 1 : (_curMonth + 1);		
		updateCalendarWithDate(_curYear, _curMonth, _curDate);
		//updateTasksView(_curYear, _curMonth, _curDate);
		this.blur();
	}
	
	function setHeadText(year, month){
		document.getElementById("calendar_date_show").innerHTML = year + (month < 10 ? "-0" : "-") + month;
	}
	
	function updateCalendarWithDate(year, month, date){
		setHeadText(year, month);
		document.getElementById(_selectedColId).style.background = TABLE_BODY_BK_COLOR;
		var col = document.getElementById(genColId(year, month, date));
		if(col == null || year != _curYear || month != _curMonth){
			buildData(_table, year, month, date);
		}
		else {
			decorateSelectedCol(col);
		}		
	}
	
	this.updateCalendarWith = function(year, month, date){
		updateCalendarWithDate(year, month, date);		
	}
}